unit uConfig;

{$mode objfpc}{$H+}

interface

uses
    SysUtils, Forms, typinfo, contnrs,
    XMLConf;

type

    TConfFile = class;

    { TConfig }

    // Representing whole application configuration
    TConfig = class
    private
        FFiles: TFPObjectList;
    private
        FPath: string;
        procedure SetPath(AValue: string);
    protected
        // General initialization
        procedure Init; virtual;
        // General finalization
        procedure Done; virtual;

        // Add config files here
        procedure InitFiles; virtual;

        function FileAdd(const aName: string): TConfFile;
    public
        constructor Create;
        destructor Destroy;

        property Path: string read FPath write SetPath;
    end;

    { TConfFile }

    // Single configuration file
    TConfFile = class
    private // Private fields & methods
        FStorage: TXMLConfig;
    private // Properties
        FFileName: string;
        procedure SetFileName(AValue: string);
    protected
    public
        // Config file name.
        // Only file name without path and extension
        property FileName: string read FFileName write SetFileName;
    end;


    { TConfSection }

    // Section in the configuration file
    TConfSection = class
    private
        FName: string;
        FStorage: TXMLConfig;
        procedure SetName(AValue: string);
    private
        procedure SaveValueInt(const AName; const AValue: integer);
        procedure SaveValueStr(const AName; const AValue: string);
        procedure SaveValueBoo(const AName; const AValue: boolean);

        procedure SaveRTTIProps;
        procedure LoadRTTIProps;
    protected
        procedure Load; virtual;
        procedure Save; virtual;
        procedure SetDefaults; virtual; abstract;
    public
        procedure Create;

        property Name: string read FName write SetName;
    end;

    { TConfList }

    // List of the similar sections in the config
    TConfList = class(TConfSection)
    private
    private
    protected
    public
    end;

    { TConfGeneral }

    TConfGeneral = class(TConfSection)
    private
        FSingleInstance: boolean;
        procedure SetSingleInstance(AValue: boolean);
    protected
        procedure SetDefaults; override;
    public
    published
        property SingleInstance: boolean read FSingleInstance write SetSingleInstance;
    end;

    { TConfForm }

    TConfForm = class(TConfSection)
    private
        FHeight: integer;
        FLeft: integer;
        FMonitor: integer;
        FState: TWindowState;
        FTop: integer;
        FWidth: integer;
        procedure SetHeight(AValue: integer);
        procedure SetLeft(AValue: integer);
        procedure SetMonitor(AValue: integer);
        procedure SetState(AValue: TWindowState);
        procedure SetTop(AValue: integer);
        procedure SetWidth(AValue: integer);
    protected
        procedure Load; override;
        procedure Save; override;
        procedure SetDefaults; override;
    public
        procedure GetFromForm(AForm: TForm);
        procedure SetToForm(AForm: TForm);
    published
        property Monitor: integer read FMonitor write SetMonitor;
        property Left: integer read FLeft write SetLeft;
        property Top: integer read FTop write SetTop;
        property Width: integer read FWidth write SetWidth;
        property Height: integer read FHeight write SetHeight;
        property State: TWindowState read FState write SetState;
    end;

    { TConfFont }

    TConfFont = class(TConfSection)
    private
        FCode: string;
        FSize: integer;
        procedure SetCode(AValue: string);
        procedure SetSize(AValue: integer);
    published
        property Code: string read FCode write SetCode;
        property Size: integer read FSize write SetSize;
    end;

    { TConfUI }

    TConfUI = class(TConfSection)
    private
        FMainUIFont: string;
        FPageButtonFontSize: integer;
        FPageButtonWidth: integer;
        FPanelsVisible: boolean;
        FPanelsWidth: integer;
        procedure SetMainUIFont(AValue: string);
        procedure SetPageButtonFontSize(AValue: integer);
        procedure SetPageButtonWidth(AValue: integer);
        procedure SetPanelsVisible(AValue: boolean);
        procedure SetPanelsWidth(AValue: integer);
    protected
        procedure Load; override;
        procedure Save; override;
        procedure SetDefaults; override;
    published
        property MainUIFont: string read FMainUIFont write SetMainUIFont;
        property PageButtonWidth: integer read FPageButtonWidth write SetPageButtonWidth;
        property PageButtonFontSize: integer read FPageButtonFontSize write SetPageButtonFontSize;

        property PanelsVisible: boolean read FPanelsVisible write SetPanelsVisible;
        property PanelsWidth: integer read FPanelsWidth write SetPanelsWidth;
    end;

implementation

{ TConfFile }

procedure TConfFile.SetFileName(AValue: string);
begin
    if FFileName = AValue then
        Exit;
    FFileName := AValue;
end;

{ TConfig }

procedure TConfig.SetPath(AValue: string);
begin
    if FPath = AValue then
        Exit;
    FPath := AValue;
end;

procedure TConfig.Init;
begin
    FFiles := TFPObjectList.Create(True);
end;

procedure TConfig.Done;
begin
    FFiles.Free;
end;

procedure TConfig.InitFiles;
begin

end;

function TConfig.FileAdd(const aName: string): TConfFile;
begin

end;

constructor TConfig.Create;
begin
    Init;
end;

destructor TConfig.Destroy;
begin
    Done;
end;

{ TConfFont }

procedure TConfFont.SetCode(AValue: string);
begin
    if FCode = AValue then
        Exit;
    FCode := AValue;
end;

procedure TConfFont.SetSize(AValue: integer);
begin
    if FSize = AValue then
        Exit;
    FSize := AValue;
end;

{ TConfGeneral }

procedure TConfGeneral.SetSingleInstance(AValue: boolean);
begin
    if FSingleInstance = AValue then
        Exit;
    FSingleInstance := AValue;
end;

procedure TConfGeneral.SetDefaults;
begin
    FSingleInstance := True;
end;

{ TConfForm }

procedure TConfForm.SetHeight(AValue: integer);
begin
    if FHeight = AValue then
        Exit;
    FHeight := AValue;
end;

procedure TConfForm.SetLeft(AValue: integer);
begin
    if FLeft = AValue then
        Exit;
    FLeft := AValue;
end;

procedure TConfForm.SetMonitor(AValue: integer);
begin
    if FMonitor = AValue then
        Exit;
    FMonitor := AValue;
end;

procedure TConfForm.SetState(AValue: TWindowState);
begin
    if FState = AValue then
        Exit;
    FState := AValue;
end;

procedure TConfForm.SetTop(AValue: integer);
begin
    if FTop = AValue then
        Exit;
    FTop := AValue;
end;

procedure TConfForm.SetWidth(AValue: integer);
begin
    if FWidth = AValue then
        Exit;
    FWidth := AValue;
end;

procedure TConfForm.Load;
begin
    inherited Load;
end;

procedure TConfForm.Save;
begin
    inherited Save;
end;

procedure TConfForm.SetDefaults;
begin
    Monitor := 0;
    Left := 0;
    Top := 0;
    Width := 640;
    Height := 480;
    State := wsNormal;
end;

procedure TConfForm.GetFromForm(AForm: TForm);
begin

end;

procedure TConfForm.SetToForm(AForm: TForm);
begin

end;

{ TConfUI }

procedure TConfUI.SetMainUIFont(AValue: string);
begin
    if FMainUIFont = AValue then
        Exit;
    FMainUIFont := AValue;
end;

procedure TConfUI.SetPageButtonFontSize(AValue: integer);
begin
    if FPageButtonFontSize = AValue then
        Exit;
    FPageButtonFontSize := AValue;
end;

procedure TConfUI.SetPageButtonWidth(AValue: integer);
begin
    if FPageButtonWidth = AValue then
        Exit;
    FPageButtonWidth := AValue;
end;

procedure TConfUI.SetPanelsVisible(AValue: boolean);
begin
    if FPanelsVisible = AValue then
        Exit;
    FPanelsVisible := AValue;
end;

procedure TConfUI.SetPanelsWidth(AValue: integer);
begin
    if FPanelsWidth = AValue then
        Exit;
    FPanelsWidth := AValue;
end;

procedure TConfUI.Load;
begin
    inherited Load;
end;

procedure TConfUI.Save;
begin
    inherited Save;
end;

procedure TConfUI.SetDefaults;
begin

end;

{ TConfSection }

procedure TConfSection.SetName(AValue: string);
begin
    if FName = AValue then
        Exit;
    FName := AValue;
end;

procedure TConfSection.SaveValueInt(const AName; const AValue: integer);
begin

end;

procedure TConfSection.SaveValueStr(const AName; const AValue: string);
begin

end;

procedure TConfSection.SaveValueBoo(const AName; const AValue: boolean);
begin

end;

procedure TConfSection.SaveRTTIProps;
var
    pi: PTypeInfo;
    pd: PTypeData;
    pl: PPropList;
    pp: PPropInfo;

    i, c: smallint;
    n: string;
    v: variant;
begin
    pi := Self.ClassInfo;
    pd := GetTypeData(pi);

    c := pd^.PropCount;
    GetMem(pl, c * SizeOf(Pointer));
    c := GetPropList(pi, pl);
    try
        // Enumerate published properties
        for i := 0 to c - 1 do
        begin
            // and save it's name=value
            pp := pl^[i];
            n := pp^.Name;
            v := GetPropValue(Self, n);
            case pp^.PropType^.Kind of
                tkInteger, tkInt64, tkQWord:
                begin
                    SaveValueInt(n, v);
                end;
                tkSString, tkLString, tkAString, tkWString, tkUString:
                begin
                    SaveValueStr(n, v);
                end;
                tkBool:
                begin
                    SaveValueBoo(n, v);
                end;
                else
                    raise Exception.CreateFmt('Config: Unsupported type for property %s: %s',
                        [n, pp^.PropType^.Name]);
            end;
        end;
    finally
        FreeMem(pl);
    end;
end;

procedure TConfSection.LoadRTTIProps;
begin

end;

procedure TConfSection.Load;
begin
    // Load published props
    //LoadRTTIProps;
end;

procedure TConfSection.Save;
begin
    // Save published props
    //SaveRTTIProps;
end;

procedure TConfSection.Create;
begin
    FStorage := TXMLConfig.Create(nil);
end;

end.
